/*
 * OPIAM Suite
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package opiam.admin.faare.service.services.trombinoscope;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

import opiam.admin.faare.service.services.views.orgchart.OrgChartPanel;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;

import quantize.ImageFrame;
import quantize.Quantize;
import quantize.TestQuantize;
import Acme.JPM.Encoders.GifEncoder;

import com.lowagie.text.Document;
import com.lowagie.text.Graphic;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;


/**
 * Class which allows to generate a "Trombinoscope".
 */
public class Trombinoscope extends JPanel
{
    /** Instance of logger. */
    private static Logger _logger = Logger.getLogger(Trombinoscope.class);

    /** Type of image to generate : GIF image. */
    public static final String TYPE_GIF = "gif";

    /** Photo background. */
    private static Color photoColor = Color.lightGray;

    /** Text background. */
    private static Color textColor = Color.lightGray;

    /** Text alignment. */
    private static int align = JLabel.LEFT;

    /** Ten value. */
    private static final int TEN = 10;

    /** number of colors in a GIF file. */
    private static final int GIFCOLORS = 256;

    /** Start index in the entries list. */
    private int startIndex;

    /** Number of cells per line. */
    private int nbCols;

    /** Number of entries to take into account in the list. */
    private int nbEntries;

    /** List of entries. */
    private List entries;

    /** List of attributes to use. */
    private List attribs;

    /** Name of the property which contains the photo. */
    private String photoAttr = "photo";

    /** The photo is a collection or not. */
    private boolean photoCollection = true;

    /** List of cells. */
    private List cells = new ArrayList();

    /** Photo maximum size. */
    private final int photoSize = 100;

    /** Space between cells. */
    private final int cellSpace = 20;

//DW/2615/BeginPatch
    /** default photo file name. */
    private String defaultPhoto = null;
//DW/2615/EndPatch

    /**
     * Constructs a Trombinoscope object.
     *
     * @param si  Start index in the list of entries.
     * @param nc  Number of columns.
     * @param ne  Number of entries to take into account.
     * @param e  List of entries.
     * @param a  List of attributes to take into account.
     */
    public Trombinoscope(final int si, final int nc, final int ne,
        final List e, final List a)
    {
        startIndex = si;
        nbCols = nc;
        nbEntries = ne;
        entries = e;
        attribs = a;
    }

    /**
     * Method which sets the name of the property containing the photo.
     * Default : "photo".
     *
     * @param value  Name of the property containing the photo.
     *
     */
    public final void setPhotoAttr(final String value)
    {
        photoAttr = value;
    }

    /**
     * Method which sets the photo background color.
     * Default : lightGray.
     *
     * @param value  Color.
     *
     */
    public final void setPhotoColor(final Color value)
    {
        if (value != null)
        {
            photoColor = value;
        }
    }

    /**
     * Method which sets the text background color.
     * Default : lightGray.
     *
     * @param value  Color.
     *
     */
    public final void setTextColor(final Color value)
    {
        if (value != null)
        {
            textColor = value;
        }
    }

    /**
     * Method which sets the text alignment.
     * Default : left.
     *
     * @param talign  Alignement value.
     *
     */
    public final void setTextAlignment(final String talign)
    {
        if (talign != null)
        {
            if (talign.toUpperCase().equals("CENTER"))
            {
                align = SwingConstants.CENTER;
            }
            else if (talign.toUpperCase().equals("RIGHT"))
            {
                align = SwingConstants.RIGHT;
            }
        }
    }

    /**
     * Method which build a cell of the "Trombinoscope".
     *
     * @param index  Index of entry in list.
     *
     * @return Trombinoscope cell.
     */
    private JPanel createCell(final int index)
    {
        JPanel cell = new JPanel();
        cell.setLayout(new BorderLayout());

        //DW/2588/BeginPatch
        //cell.setBackground(Color.lightGray);
        cell.setBackground(photoColor);

        //DW/2588/EndPatch
        Object entry = entries.get(index);

        // photo
        try
        {
            byte[] photo = null;
            Object aPhoto = PropertyUtils.getProperty(entry, photoAttr);
//DW/2611/BeginPatch
            photoCollection = ((aPhoto != null) && (aPhoto instanceof Collection));
//DW/2611/EndPatch

            if (photoCollection && (aPhoto != null))
            {
                Iterator iter = ((Collection) aPhoto).iterator();

                if ((iter != null) && (iter.hasNext()))
                {
                    photo = (byte[]) iter.next();
                }
            }
            else if (aPhoto != null)
            {
                photo = (byte[]) aPhoto;
            }

//DW/2615/BeginPatch
            ImageIcon image = null;
//DW/2615/EndPatch
            if (photo != null)
            {
//DW/2615/BeginPatch
                //ImageIcon image = new ImageIcon(photo);
                image = new ImageIcon(photo);
            }
            else if (defaultPhoto != null)
            {
                image = new ImageIcon(defaultPhoto);
            }

            if (image != null)
            {
//DW/2615/EndPatch
                if ((image.getIconHeight() > photoSize) ||
                        (image.getIconWidth() > photoSize))
                {
                    Image im = image.getImage();
                    Image newIm = im.getScaledInstance(-1, photoSize,
                            Image.SCALE_FAST);
                    image = new ImageIcon(newIm);
                }

                if (image != null)
                {
                    JLabel photoLab = new JLabel(image);
                    cell.add(photoLab, BorderLayout.CENTER);
                }
            }

        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

        // attributes
        Iterator iter = attribs.iterator();
        String attr = "";
        JPanel attrPan = new JPanel();

        //DW/2588/BeginPatch
        attrPan.setBackground(textColor);

        //DW/2588/EndPatch
        //DW/2589/BeginPatch
        //attrPan.setLayout(new BoxLayout(attrPan, BoxLayout.Y_AXIS));
        attrPan.setLayout(new GridLayout(0, 1));

        //DW/2589/EndPatch
        while (iter.hasNext())
        {
            try
            {
                attr = (String) iter.next();

                String value = (String) PropertyUtils.getProperty(entry, attr);

                if (value != null)
                {
                    JLabel label = new JLabel(value);

                    //DW/2589/BeginPatch
                    //label.setHorizontalAlignment(label.CENTER);
                    label.setHorizontalAlignment(align);

                    //DW/2589/EndPatch
                    attrPan.add(label);
                }
                else
                {
                    JLabel label = new JLabel(" ");
                    label.setHorizontalAlignment(SwingConstants.CENTER);
                    attrPan.add(label);
                }
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
                _logger.error(attr + " : " + ex.getMessage());
            }
        }

        cell.add(attrPan, BorderLayout.SOUTH);

        Hashtable infos = new Hashtable();
        infos.put("CELL", cell);

        try
        {
            infos.put(OrgChartPanel.DN, PropertyUtils.getProperty(entry, "dn"));
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            _logger.error("dn : " + ex.getMessage());
        }

        cells.add(infos);

        return cell;
    }

    /**
     * Method which builds the "Trombinoscope".
     */
    public final void doIt()
    {
        this.setLayout(new GridLayout(0, nbCols, cellSpace, cellSpace));
        this.setBackground(Color.white);

        if (entries == null)
        {
            return;
        }

        int len = entries.size() - startIndex;

        if (len < nbEntries)
        {
            nbEntries = len;
        }

        int nbLines = ((nbEntries + nbCols) - 1) / nbCols;

        for (int curline = 0; curline < nbLines; curline++)
        {
            for (int curcol = 0; curcol < nbCols; curcol++)
            {
                if (((curline * nbCols) + curcol) < nbEntries)
                {
                    add(createCell((curline * nbCols) + curcol + startIndex));
                }
            }
        }
    }

    /**
     * Method which generates the "Trombinoscope".
     *
     * @param imgtype  Type of image to generate.
     *
     * @return a list with : image as first element (java.io.ByteArrayOutputStream)
     *                  as second element, a java.util.Hashtable with for each
     *                  Trombinoscope cell :
     *                  the entry dn (OrgChartPanel.DN), the coordinates
     *                  (OrgChartPanel.XCOORD, OrgChartPanel.YCOORD,
     *                   OrgChartPanel.WIDTH and OrgChartPanel.HEIGHT)
     */
    public final List doPrint(final String imgtype)
    {
        List lresult = new ArrayList();

        int maxX = 0;
        int maxY = 0;

        Iterator iter = cells.iterator();

        while (iter.hasNext())
        {
            Hashtable info = (Hashtable) iter.next();
            JPanel cell = (JPanel) info.get("CELL");
            int x = (int) cell.getBounds().getX();
            int y = (int) cell.getBounds().getY();
            int w = (int) cell.getBounds().getWidth();
            int h = (int) cell.getBounds().getHeight();

            if ((x + w) > maxX)
            {
                maxX = x + w;
            }

            if ((y + h) > maxY)
            {
                maxY = y + h;
            }

            info.put(OrgChartPanel.XCOORD, new Integer(x));
            info.put(OrgChartPanel.YCOORD, new Integer(y));
            info.put(OrgChartPanel.WIDTH, new Integer(w));
            info.put(OrgChartPanel.HEIGHT, new Integer(h));
        }

        try
        {
            BufferedImage img = new BufferedImage(maxX, maxY,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics = img.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);           
            this.paint(graphics);         
           

            ByteArrayOutputStream result = new ByteArrayOutputStream();

            if (imgtype.toLowerCase().equals(TYPE_GIF))
            {
                //DW/2597/BeginPatch
                int[][] pixels = TestQuantize.getPixels(img);
                int[] palette = Quantize.quantizeImage(pixels, GIFCOLORS);
                ImageFrame reduced = new ImageFrame();
                reduced.setImage(palette, pixels);

                Image gifimg = reduced.getImage();
                new GifEncoder(gifimg, result).encode();

                /*
                                new GifEncoder(img, result).encode();
                */

                //DW/2597/EndPatch
//DW/2641/BeginPatch
                reduced.dispose();
//DW/2641/EndPatch
            }
            else
            {
                ImageIO.write(img, imgtype.toLowerCase(), result);
            }

            lresult.add(result);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            _logger.error("doPrint : " + ex.getMessage());
        }

        lresult.add(cells);

        return lresult;
    }

    //DW/2591/BeginPatch

    /**
     * Method which generates the "Trombinoscope" as a PDF stream.
     *
     * @return PDF Trombinoscope as a stream.
     *
     */
    public final ByteArrayOutputStream doPrintAsPdf()
    {
        int maxX = 0;
        int maxY = 0;

        Iterator iter = cells.iterator();

        while (iter.hasNext())
        {
            Hashtable info = (Hashtable) iter.next();
            JPanel cell = (JPanel) info.get("CELL");
            int x = (int) cell.getBounds().getX();
            int y = (int) cell.getBounds().getY();
            int w = (int) cell.getBounds().getWidth();
            int h = (int) cell.getBounds().getHeight();

            if ((x + w) > maxX)
            {
                maxX = x + w;
            }

            if ((y + h) > maxY)
            {
                maxY = y + h;
            }

            info.put(OrgChartPanel.XCOORD, new Integer(x));
            info.put(OrgChartPanel.YCOORD, new Integer(y));
            info.put(OrgChartPanel.WIDTH, new Integer(w));
            info.put(OrgChartPanel.HEIGHT, new Integer(h));
        }

        Document document = new Document(new Rectangle(maxX, maxY), TEN, TEN,
                TEN, TEN);
        ByteArrayOutputStream buf = new ByteArrayOutputStream();

        try
        {
            PdfWriter writer = PdfWriter.getInstance(document, buf);
            document.open();

            PdfContentByte cb = writer.getDirectContent();

            Graphic grx = new Graphic();
            BufferedImage img = new BufferedImage(maxX, maxY,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics = img.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);    
            this.paint(graphics);

            ByteArrayOutputStream result = new ByteArrayOutputStream();
            ImageIO.write(img, "jpg", result);

            byte[] data = result.toByteArray();
            com.lowagie.text.Image img1 = com.lowagie.text.Image.getInstance(data);
            img1.setAbsolutePosition(0, 0);
            cb.addImage(img1);
            
           /* try{
            	File f = new File( "C:\\out2.jpg" );
            	f.createNewFile();
            	FileOutputStream out = new FileOutputStream(f);
            	out.write(result.toByteArray());
            	out.close();
            }catch(Exception e){};*/
        }
        catch (Exception e)
        {
            _logger.error(e.getMessage());
        }

        document.close();

        return buf;
    }
    //DW/2591/EndPatch

//DW/2615/BeginPatch
    /**
     * Sets default photo file name.
     *
     * @param value  File name.
     */
    public void setDefaultPhoto(String value)
    {
//DW/2697/BeginPatch
        try
        {
           value = URLDecoder.decode (value, "UTF-8");
        }
        catch (Exception ex)
        {
           _logger.error ("invalid photo name");
        }
//DW/2697/EndPatch
        defaultPhoto = value;
    }
//DW/2615/EndPatch

}
